package com.ywu.standard.gateway.handler.user;

import com.ywu.admin.user.spi.dto.UserDto;
import com.ywu.admin.user.spi.spi.UserSpi;
import com.ywu.admin.user.spi.entity.UserEntity;
import com.ywu.boot.config.BootConfigAppConfig;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.boot.context.YwuContextUser;
import com.ywu.common.constant.CommonConstant;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.mapper.YwuBeanMapper;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.AesUtils;
import com.ywu.standard.gateway.handler.user.impl.UserHandlerInterface;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName UserInfoHandler
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/5/26 12:04
 * @Version 1.0
 **/
@Component
@Slf4j
@Order(2)
public class UserInfoHandler implements UserHandlerInterface {
    private static final String USER_HEADER_KEY = "X-Pix-Ywu-User-Info";

    private static final String GUEST_ACCOUNT = "guest";

    @Autowired
    private UserSpi userSpi;

    @Autowired
    private BootConfigAppConfig bootConfigAppConfig;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String YWU_GATEWAY_USER_INFO_REDIS_KEY = "YWU_GATEWAY_USER_INFO:gateway:";

    @Override
    public Object handle(ServerWebExchange exchange) {
        log.debug("UserInfoHandler begin");
        if (YwuContextHolder.getCurrentContext().isFilterChain()) {
            log.info("UserInfoHandler isFilterChain is true");
            return exchange;
        }
        // 从上下文中获取账号
        String userAccount = YwuContextHolder.getCurrentContext().getYwuContextUser().getUserAccount();
        UserEntity userEntity = null;
        // 如果是游客的话则进行跳过，不进行查询
        if (GUEST_ACCOUNT.equals(userAccount)) {
            userEntity = new UserEntity();
            userEntity.setUserAccount(userAccount);
        } else {
            // 优先从缓存中获取数据
            String redisInfo = redisTemplate.opsForValue().get(YWU_GATEWAY_USER_INFO_REDIS_KEY + userAccount);
            if (Objects.nonNull(redisInfo)) {
                log.debug("gateway query user info using redis cache");
                userEntity = GsonUtils.deserialize(redisInfo, UserEntity.class);
            } else {
                UserDto userDto = new UserDto();
                userDto.setUserAccount(userAccount);
                CompletableFuture<CommonResult<UserEntity>> resultCompletableFuture =
                        CompletableFuture.supplyAsync(() -> userSpi.queryUserByUserAccount(userDto));
                CommonResult<UserEntity> listCommonResult;
                try {
                    listCommonResult = resultCompletableFuture.get();
                } catch (InterruptedException | ExecutionException e) {
                    log.error("UserInfoHandler CompletableFuture spi query error {}", e.getMessage());
                    return CommonResult.error().setCode(CommonConstant.USER_QUERY_INFO_ERROR).setErrorCode(CommonConstant.USER_QUERY_INFO_ERROR_MESSAGE)
                            .setMessage("用户查询异常!");
                }
                if (!StringUtils.equals("200", listCommonResult.getCode()) || Objects.isNull(listCommonResult.getData())) {
                    return CommonResult.error().setCode(CommonConstant.USER_QUERY_INFO_ERROR).setErrorCode(CommonConstant.USER_QUERY_INFO_ERROR_MESSAGE)
                            .setMessage("用户查询失败!");
                }
                userEntity = listCommonResult.getData();
                // 添加缓存
                redisTemplate.opsForValue().set(YWU_GATEWAY_USER_INFO_REDIS_KEY + userAccount, GsonUtils.serialize(userEntity));
                redisTemplate.expire(YWU_GATEWAY_USER_INFO_REDIS_KEY + userAccount, 1, TimeUnit.HOURS);
            }
        }
        YwuContextUser userInfo = YwuBeanMapper.map(userEntity, YwuContextUser.class);
        YwuContextHolder.getCurrentContext().setYwuContextUser(userInfo);
        String userEntityInfo = GsonUtils.serialize(userInfo);
        String encryptUserInfo;
        try {
            encryptUserInfo = AesUtils.encrypt(userEntityInfo, bootConfigAppConfig.getSecretKey());
        } catch (Exception e) {
            log.error("UserInfoHandler userInfo encrypt error {}", e.getMessage());
            return CommonResult.error().setCode(CommonConstant.USER_QUERY_INFO_ERROR).setErrorCode(CommonConstant.USER_QUERY_INFO_ERROR_MESSAGE)
                    .setMessage("用户信息加密异常!");
        }
        log.debug("UserInfoHandler userInfo header str is {}", encryptUserInfo);
        ServerHttpRequest mutatedTraceRequest = exchange.getRequest().mutate().header(USER_HEADER_KEY, encryptUserInfo).build();
        return exchange.mutate().request(mutatedTraceRequest).build();
    }
}
